package com.rpcdemo.rpc.transport;

import com.rpcdemo.rpc.Dispatcher;
import com.rpcdemo.rpc.protocol.MyContent;
import com.rpcdemo.rpc.protocol.MyHeader;
import com.rpcdemo.util.PackMsg;
import com.rpcdemo.util.SeriaUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ServerRequestHandler extends ChannelInboundHandlerAdapter {

    Dispatcher dispatcher = Dispatcher.getDispatcher();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        PackMsg packMsg = (PackMsg) msg;

        ctx.executor().parent().next().execute(() -> {

            String clazz = packMsg.getContent().getName();
            String methodName = packMsg.getContent().getMethodName();
            Class<?>[] parameterTypes = packMsg.getContent().getParameterTypes();
            Object[] args = packMsg.getContent().getArgs();

            Object impl = dispatcher.get(clazz);

            Class<?> implClass = impl.getClass();
            Object res = null;
            try {
                Method method = implClass.getMethod(methodName, parameterTypes);
                res = method.invoke(impl, args);

            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }

            MyContent respBody = new MyContent();
            respBody.setRes(res);
            byte[] byteBody = SeriaUtil.encode(respBody);

            MyHeader header = packMsg.getHeader();
            header.setFlag(0x14141424);
            header.setDataLen(byteBody.length);
            byte[] byteHeader = SeriaUtil.encode(header);

            ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(byteHeader.length + byteBody.length);
            buf.writeBytes(byteHeader);
            buf.writeBytes(byteBody);
            ctx.writeAndFlush(buf);
        });


    }
}